home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / abuse / src / menu.c < prev    next >
C/C++ Source or Header  |  1996-08-30  |  20KB  |  781 lines

  1. #include "menu.hpp"
  2. #include "lisp.hpp"
  3. #include "game.hpp"
  4. #include "timing.hpp"
  5. #include "game.hpp"
  6. #include "id.hpp"
  7. #include "pmenu.hpp"
  8. #include "gui.hpp"
  9. #include "property.hpp"
  10. #include "dev.hpp"
  11. #include "clisp.hpp"
  12. #include "gamma.hpp"
  13. #include "dprint.hpp"
  14. #include "demo.hpp"
  15. #include "loadgame.hpp"
  16. #include "scroller.hpp"
  17. #include "netcfg.hpp"
  18. #include <math.h>
  19. #include "sock.hpp"
  20.  
  21. extern net_protocol *prot;
  22. jwindow *volume_window=NULL;
  23. extern int confirm_quit();
  24. extern int registered;
  25.  
  26. //percent is 0..256
  27. void tint_area(int x1, int y1, int x2, int y2, int r_to, int g_to, int b_to, int percent)
  28. {
  29.   int x,y;
  30.   short cx1,cy1,cx2,cy2;
  31.   screen->get_clip(cx1,cy1,cx2,cy2);
  32.   if (x1<cx1) x1=cx1;
  33.   if (y1<cy1) y1=cy1;
  34.   if (x2>cx2) x2=cx2;
  35.   if (y2>cy2) y2=cy2;
  36.   if (x2<x1 || y2<y1) return ;
  37.  
  38.   percent=256-percent;
  39.  
  40.   for (y=y1;y<=y2;y++)
  41.   {
  42.     unsigned char *sl=screen->scan_line(y)+x1;
  43.     for (x=x1;x<=x2;x++,sl++)
  44.     {
  45.       unsigned char *paddr=(unsigned char *)pal->addr()+(*sl)*3;
  46.       unsigned char r=((*(paddr++))-r_to)*percent/256+r_to;
  47.       unsigned char g=((*(paddr++))-g_to)*percent/256+g_to;
  48.       unsigned char b=((*(paddr++))-b_to)*percent/256+b_to;
  49.       *sl=color_table->lookup_color((r)>>3,(g)>>3,(b)>>3);
  50.     }
  51.   }
  52.   screen->add_dirty(x1,y1,x2,y2);  
  53. }
  54.  
  55. void darken_area(int x1, int y1, int x2, int y2, int amount)
  56. {
  57.   int x,y;
  58.   short cx1,cy1,cx2,cy2;
  59.   screen->get_clip(cx1,cy1,cx2,cy2);
  60.   if (x1<cx1) x1=cx1;
  61.   if (y1<cy1) y1=cy1;
  62.   if (x2>cx2) x2=cx2;
  63.   if (y2>cy2) y2=cy2;
  64.   if (x2<x1 || y2<y1) return ;
  65.  
  66.   for (y=y1;y<=y2;y++)
  67.   {
  68.     unsigned char *sl=screen->scan_line(y)+x1;
  69.     for (x=x1;x<=x2;x++,sl++)
  70.     {
  71.       unsigned char *paddr=(unsigned char *)pal->addr()+(*sl)*3;
  72.       unsigned char r=(*(paddr++))*amount/256;
  73.       unsigned char g=(*(paddr++))*amount/256;
  74.       unsigned char b=(*(paddr++))*amount/256;
  75.       *sl=color_table->lookup_color((r)>>3,(g)>>3,(b)>>3);
  76.     }
  77.   }
  78.   screen->add_dirty(x1,y1,x2,y2);
  79. }
  80.  
  81. void dark_wiget(int x1, int y1, int x2, int y2, int br, int dr, int amount)
  82. {
  83.   screen->add_dirty(x1,y1,x2,y2);
  84.   screen->line(x1,y1,x1,y2,br);
  85.   screen->line(x1+1,y1,x2,y1,br);
  86.   screen->line(x2,y1+1,x2,y2,dr);
  87.   screen->line(x1+1,y2,x2,y2,dr);
  88.   darken_area(x1+1,y1+1,x2-1,y2-1,amount);  
  89. }
  90.  
  91. char *men_str(void *arg)
  92. {
  93.   switch (item_type(arg))
  94.   {
  95.     case L_STRING : 
  96.     { return lstring_value(arg); } break;
  97.     case L_CONS_CELL : 
  98.     { return lstring_value(CAR(arg)); } break;
  99.     default : 
  100.     {
  101.       lprint(arg);
  102.       printf(" is not a valid menu option\n");
  103.       exit(0);
  104.     }
  105.   }
  106.   return NULL;
  107. }
  108.  
  109. void main_menu();
  110.  
  111. int menu(void *args, JCFont *font)             // reurns -1 on esc
  112. {
  113.   main_menu();
  114.   char *title=NULL;
  115.   if (!NILP(CAR(args)))
  116.     title=lstring_value(CAR(args));
  117.   Cell *def=lcar(lcdr(lcdr(args)));
  118.   args=CAR(CDR(args));
  119.  
  120.   int options=list_length(args);
  121.   int mh=(font->height()+1)*options+10,maxw=0;
  122.  
  123.   Cell *c=(Cell *)args;
  124.   for (;!NILP(c);c=CDR(c))
  125.   {
  126.     if (strlen(men_str(CAR(c)))>maxw)
  127.       maxw=strlen(men_str(CAR(c)));
  128.   }
  129.   
  130.   int mw=(font->width())*maxw+20;
  131.   int mx=screen->width()/2-mw/2,
  132.       my=screen->height()/2-mh/2;
  133.   
  134.  
  135.   screen->add_dirty(mx,my,mx+mw-1,my+mh-1);
  136.  
  137.   if (title)
  138.   {
  139.     int tl=strlen(title)*font->width();
  140.     int tx=screen->width()/2-tl/2;
  141.     dark_wiget(tx-2,my-font->height()-4,tx+tl+2,my-2,eh->medium_color(),eh->dark_color(),180);
  142.     font->put_string(screen,tx+1,my-font->height()-2,title,eh->bright_color());
  143.   }
  144.   
  145.   dark_wiget(mx,my,mx+mw-1,my+mh-1,eh->medium_color(),eh->dark_color(),200);
  146.  
  147.  
  148.   int y=my+5;
  149.   for (c=(Cell *)args;!NILP(c);c=CDR(c))
  150.   {
  151.     char *ms=men_str(CAR(c));
  152.     font->put_string(screen,mx+10+1,y+1,ms,eh->black());
  153.     font->put_string(screen,mx+10,y,ms,eh->bright_color());
  154.     y+=font->height()+1;
  155.   }
  156.   
  157.  
  158.   eh->flush_screen();
  159.   event ev;
  160.   int choice=0,done=0;
  161.   int bh=font->height()+3;
  162.   image *save=new image(mw-2,bh);
  163.   int color=128,cdir=50;
  164.   
  165.   time_marker *last_color_time=NULL; 
  166.   if (!NILP(def))
  167.     choice=lnumber_value(def);
  168.   do
  169.   {
  170.     eh->flush_screen();
  171.     if (eh->event_waiting())
  172.     {
  173.       eh->get_event(ev);
  174.       if (ev.type==EV_KEY)
  175.       {
  176.     switch (ev.key)
  177.     {
  178.       case JK_ESC : 
  179.       { choice=-1; done=1; } break;
  180.       case JK_ENTER :
  181.       { done=1; } break;
  182.       case JK_DOWN : 
  183.       { if (choice<options-1) 
  184.         choice++;
  185.       else choice=0;
  186.       } break;
  187.       case JK_UP :
  188.       {
  189.         if (choice>0)
  190.         choice--;
  191.         else choice=options-1;
  192.       } break;              
  193.     }
  194.       } else if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
  195.       {
  196.     if (ev.mouse_move.x>mx && ev.mouse_move.x<mx+mw && ev.mouse_move.y>my &&
  197.         ev.mouse_move.y<my+mh)
  198.     {
  199.       int msel=(ev.mouse_move.y-my)/(font->height()+1);
  200.       if (msel>=options) msel=options-1;
  201.       if (msel==choice)                    // clicked on already selected item, return it
  202.         done=1;
  203.       else choice=msel;                    // selects an item
  204.     }
  205.       }
  206.     }
  207.  
  208.     time_marker cur_time;
  209.     if (!last_color_time || (int)(cur_time.diff_time(last_color_time)*1000)>120)
  210.     {       
  211.       if (last_color_time)
  212.         delete last_color_time;
  213.       last_color_time=new time_marker;
  214.  
  215.       int by1=(font->height()+1)*choice+my+5-2;
  216.       int by2=by1+bh-1;
  217.  
  218.       screen->put_part(save,0,0,mx+1,by1,mx+mw-2,by2);
  219.       tint_area(mx+1,by1,mx+mw-2,by2,63,63,63,color);
  220.  
  221.       char *cur=men_str(nth(choice,args));
  222.       font->put_string(screen,mx+10+1,by1+3,cur,eh->black());
  223.       font->put_string(screen,mx+10,by1+2,cur,eh->bright_color());
  224.       screen->rectangle(mx+1,by1,mx+mw-2,by2,eh->bright_color());
  225.  
  226.       color+=cdir;
  227.  
  228.       if (color<12 || color>256)
  229.       {
  230.     cdir=-cdir;
  231.     color+=cdir;
  232.       }
  233.       eh->flush_screen();
  234.       save->put_image(screen,mx+1,by1);
  235.     } else milli_wait(10);
  236.  
  237.   } while (!done);
  238.   if (last_color_time)
  239.     delete last_color_time;
  240.   delete save;
  241.   the_game->draw(the_game->state==SCENE_STATE);
  242.  
  243.   if (choice!=-1)
  244.   {
  245.     void *val=nth(choice,args);
  246.     if (item_type(val)==L_CONS_CELL)   // is there another value that the user want us to return?
  247.       return lnumber_value(lcdr(val));  
  248.   }
  249.   return choice;
  250. }
  251.  
  252.  
  253. static void draw_vol(image *screen, int x1, int y1, int x2, int y2, int t, int max, int c1, int c2, int slider)
  254. {
  255.   int dx=x1+t*(x2-x1)/max;
  256.   if (t!=0)
  257.   {
  258.     cash.img(slider)->put_image(screen,x1,y1);    
  259. //    screen->bar(x1,y1,dx,y2,c1);
  260.   }
  261.   else dx--;
  262.  
  263.   if (dx<x2)
  264.     screen->bar(dx+1,y1,x2,y2,c2);
  265. }
  266.  
  267. static void draw_sfx_vol(int slider)
  268. {
  269.   draw_vol(volume_window->screen,6,16,34,22,sfx_volume,127,pal->find_closest(200,75,19),
  270.        pal->find_closest(40,0,0),slider);
  271. }
  272.  
  273. static void draw_music_vol(int slider)
  274. {
  275.   draw_vol(volume_window->screen,6,61,34,67,music_volume,127,pal->find_closest(255,0,0),
  276.        pal->find_closest(40,0,0),slider);
  277. }
  278.  
  279. static void create_volume_window()
  280. {
  281. /*  int vx=WINDOW_FRAME_LEFT,vy=WINDOW_FRAME_TOP+eh->font()->height()*2,scroller_height=130,bh=eh->font()->height()+5;
  282.  
  283.   volume_window=eh->new_window(prop->getd("volume_x",xres/2-20),
  284.                    prop->getd("volume_y",yres/2-50),
  285.                    -1,
  286.                    -1,
  287.                    new scroller(vx,vy,LOWER_SFX,0,scroller_height,0,127,
  288.                    new scroller(vx+30,vy,LOWER_MUSIC,0,scroller_height,0,127,NULL)),symbol_str("VOLUME"));
  289.   event ev;
  290.   int done=0;
  291.   do
  292.   {
  293.     eh->flush_screen();
  294.     eh->get_event(ev);
  295.     if (ev.type==EV_CLOSE_WINDOW && ev.window==volume_window) done=1;    
  296.   } while (!done);
  297.   eh->close_window(volume_window);
  298.   volume_window=NULL; */
  299.  
  300.  
  301.   char *ff="art/frame.spe";
  302.   int t=SPEC_IMAGE;
  303.   int u_u=cash.reg(ff,"u_u",t,1),
  304.       u_d=cash.reg(ff,"u_u",t,1),
  305.       u_ua=cash.reg(ff,"u_ua",t,1),
  306.       u_da=cash.reg(ff,"u_da",t,1),
  307.  
  308.       d_u=cash.reg(ff,"d_u",t,1),
  309.       d_d=cash.reg(ff,"d_u",t,1),
  310.       d_ua=cash.reg(ff,"d_ua",t,1),
  311.       d_da=cash.reg(ff,"d_da",t,1),
  312.       slider=cash.reg(ff,"volume_slide",t,1);
  313.   
  314.   volume_window=eh->new_window(prop->getd("volume_x",xres/2-20),
  315.                    prop->getd("volume_y",yres/2-50),
  316.                    41-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT-2,
  317.                    101-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM,
  318.                  new ico_button(10,27,ID_SFX_DOWN,d_u,d_d,d_ua,d_da,
  319.                  new ico_button(21,27,ID_SFX_UP,u_u,u_d,u_ua,u_da,
  320.                              new info_field(15,42,0,symbol_str("SFXv"),
  321.  
  322.                  new ico_button(10,72,ID_MUSIC_DOWN,d_u,d_d,d_ua,d_da,
  323.                  new ico_button(21,72,ID_MUSIC_UP,u_u,u_d,u_ua,u_da,
  324.                              new info_field(10,86,0,symbol_str("MUSICv"),
  325.                         NULL)))))));
  326.  
  327.   cash.img(cash.reg(ff,"vcontrol",t,1))->put_image(volume_window->screen,0,0);
  328.   draw_music_vol(slider);
  329.   draw_sfx_vol(slider);
  330.   volume_window->inm->redraw();
  331.   eh->grab_focus(volume_window);
  332.   eh->flush_screen();
  333.  
  334.   volume_window->inm->allow_no_selections();
  335.   volume_window->inm->clear_current();
  336.  
  337.   event ev;
  338.   do
  339.   {
  340.     do { eh->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && eh->event_waiting()); 
  341.     eh->flush_screen();
  342.     if (ev.type==EV_MESSAGE)
  343.     {
  344.       switch (ev.message.id)
  345.       {
  346.           case ID_SFX_UP :
  347.     { if (volume_window) 
  348.       {
  349.         sfx_volume+=16;
  350.         if (sfx_volume>127) sfx_volume=127;
  351.         draw_sfx_vol(slider);
  352.         char *s="sfx/ambtech1.wav";
  353.         if (sound_avail&SFX_INITIALIZED) 
  354.           cash.sfx(cash.reg(s,s,SPEC_EXTERN_SFX,1))->play(sfx_volume);
  355.       }
  356.     } break;
  357.           case ID_SFX_DOWN :
  358.     { if (volume_window) 
  359.       {
  360.         sfx_volume-=16;
  361.         if (sfx_volume<0) sfx_volume=0;
  362.         draw_sfx_vol(slider);
  363.         char *s="sfx/ambtech1.wav";
  364.         if (sound_avail&SFX_INITIALIZED) 
  365.           cash.sfx(cash.reg(s,s,SPEC_EXTERN_SFX,1))->play(sfx_volume);
  366.       }
  367.     } break;
  368.  
  369.           case ID_MUSIC_UP :
  370.     { if (volume_window) 
  371.       {
  372.         music_volume+=16;
  373.         if (music_volume>127) music_volume=127;
  374.         draw_music_vol(slider);
  375.         if (current_song) current_song->set_volume(music_volume);
  376.       }
  377.     } break;
  378.           case ID_MUSIC_DOWN :
  379.     { if (volume_window) 
  380.       {
  381.         music_volume-=16;
  382.         if (music_volume<0) music_volume=0;
  383.         draw_music_vol(slider);
  384.         if (current_song) current_song->set_volume(music_volume);
  385.       }
  386.     } break;
  387.       }
  388.     } else if (ev.type==EV_CLOSE_WINDOW || (ev.type==EV_KEY && ev.key==JK_ESC))
  389.     {
  390.       eh->close_window(volume_window);
  391.       volume_window=NULL;
  392.     }
  393.   } while (volume_window);
  394. }
  395.  
  396.  
  397. FILE *open_FILE(char *filename, char *mode);
  398.  
  399. void save_difficulty()
  400. {
  401.   FILE *fp=open_FILE("hardness.lsp","wb");
  402.   if (!fp)
  403.     dprintf("Unable to write to file hardness.lsp\n");
  404.   else 
  405.   {
  406.     fprintf(fp,"(setf difficulty '");
  407.     if (DEFINEDP(symbol_value(l_difficulty)))
  408.     {
  409.       if (symbol_value(l_difficulty)==l_extreme)
  410.         fprintf(fp,"extreme)\n");
  411.       else if (symbol_value(l_difficulty)==l_hard)
  412.         fprintf(fp,"hard)\n");
  413.       else if (symbol_value(l_difficulty)==l_easy)
  414.         fprintf(fp,"easy)\n");
  415.       else 
  416.         fprintf(fp,"medium)\n");
  417.     } else 
  418.        fprintf(fp,"medium)\n");
  419.     fclose(fp);
  420.   }
  421. }
  422.  
  423. void fade_out(int steps);
  424. void fade_in(image *im, int steps);
  425.  
  426.  
  427. void show_sell(int abortable)
  428. {
  429.   void *ss=make_find_symbol("sell_screens");
  430.   if (!DEFINEDP(symbol_value(ss)))
  431.   {
  432.     int sp=current_space;
  433.     current_space=PERM_SPACE;
  434. //    char *prog="((\"art/help.spe\" . \"sell2\")(\"art/help.spe\" . \"sell4\")(\"art/help.spe\" . \"sell3\")(\"art/endgame.spe\" . \"credit\"))";
  435. //    char *prog="((\"art/endgame.spe\" . \"credit\") (\"art/help.spe\" . \"sell6\"))";
  436.     char *prog="((\"art/endgame.spe\" . \"credit\"))";
  437.     set_symbol_value(ss,compile(prog));
  438.     current_space=sp;
  439.   }
  440.  
  441.   if (DEFINEDP(symbol_value(ss)))
  442.   {
  443.     image blank(2,2); blank.clear();
  444.     eh->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
  445.  
  446.     ss=symbol_value(ss);
  447.     int quit=0;
  448.     while (ss && !quit)
  449.     {
  450.       int im=cash.reg_object("art/help.spe",CAR(ss),SPEC_IMAGE,1);
  451.       fade_in(cash.img(im),16);
  452.  
  453.       event ev;
  454.       do
  455.       { eh->flush_screen();
  456.     eh->get_event(ev);
  457.       } while (ev.type!=EV_KEY);
  458.       if (ev.key==JK_ESC && abortable)
  459.         quit=1;
  460.       fade_out(16);
  461.       ss=CDR(ss);
  462.     }
  463.     eh->set_mouse_shape(cash.img(c_normal)->copy(),1,1);
  464.   }
  465. }
  466.  
  467.  
  468. void menu_handler(event &ev, input_manager *inm)
  469. {
  470.   switch (ev.type)
  471.   {
  472.     case EV_MESSAGE :
  473.     {
  474.       switch (ev.message.id)
  475.       {
  476.     case ID_LIGHT_OFF :
  477.     if (!volume_window)
  478.     {
  479.       gamma_correct(pal,1);
  480.     } break;
  481.     case ID_RETURN :
  482.     if (!volume_window)
  483.     {
  484.       the_game->set_state(RUN_STATE);
  485.     } break;
  486.     case ID_START_GAME :
  487.     if (!volume_window)
  488.     {        
  489.       the_game->load_level(level_file);
  490.       the_game->set_state(RUN_STATE);
  491.       view *v;
  492.       for (v=player_list;v;v=v->next)
  493.         if (v->focus)
  494.           v->reset_player();
  495.        
  496.     } break;
  497.  
  498.    
  499.         case ID_LOAD_PLAYER_GAME :
  500.     if (!volume_window)
  501.     {
  502.       int got_level=load_game(0,symbol_str("LOAD"));
  503.       the_game->reset_keymap();
  504.       if (got_level)
  505.       {
  506.         char name[50];
  507.         sprintf(name,"save%04d.spe",got_level);
  508.         the_game->load_level(name);
  509.         the_game->set_state(RUN_STATE);        
  510.       }
  511.     } break;
  512.  
  513.  
  514.     case ID_VOLUME : 
  515.     if (!volume_window)
  516.     { create_volume_window(); } break;
  517.  
  518.     case ID_MEDIUM :
  519.     {
  520.       set_symbol_value(l_difficulty,l_medium);
  521.       save_difficulty();
  522.     } break;
  523.     case ID_HARD :
  524.     {
  525.       set_symbol_value(l_difficulty,l_hard);
  526.       save_difficulty();
  527.     } break;
  528.     case ID_EXTREME :
  529.     {
  530.       set_symbol_value(l_difficulty,l_extreme);
  531.       save_difficulty();
  532.     } break;
  533.     case ID_EASY :
  534.     {
  535.       set_symbol_value(l_difficulty,l_easy);
  536.       save_difficulty();
  537.     } break;
  538.  
  539.     case ID_NETWORKING :
  540.     {
  541.       if (!volume_window)
  542.       {
  543.         net_configuration *cfg=new net_configuration;
  544.         if (cfg->input())
  545.         {
  546.           if (main_net_cfg) delete main_net_cfg;
  547.           main_net_cfg=cfg;
  548.         } else delete cfg;
  549.         the_game->draw(0);
  550.         inm->redraw();
  551.       }
  552.     } break;
  553.               
  554.     case ID_SHOW_SELL :
  555.     if (!volume_window)
  556.     { 
  557.       show_sell(1); 
  558.       screen->clear();
  559.       if (title_screen>=0)
  560.       {
  561.         image *tit=cash.img(title_screen);
  562.           tit->put_image(screen,screen->width()/2-tit->width()/2,
  563.                           screen->height()/2-tit->height()/2);
  564.       }
  565.       inm->redraw();
  566.       fade_in(NULL,8);
  567.       eh->flush_screen(); 
  568.  
  569.     } break;
  570.       } break;
  571.     } break;
  572.     case EV_CLOSE_WINDOW :
  573.     {
  574.       if (ev.window==volume_window)
  575.       { eh->close_window(volume_window); volume_window=NULL; }
  576.     } break;
  577.   }
  578. }
  579.  
  580. void *current_demo=NULL;
  581.  
  582. static ico_button *load_icon(int num, int id, int x, int y, int &h, ifield *next, char *key)
  583. {
  584.   char name[20];
  585.   char *base="newi";
  586.   int a,b,c;
  587.   sprintf(name,"%s%04d.pcx",base,num*3+1);
  588.   a=cash.reg("art/icons.spe",name,SPEC_IMAGE,1);
  589.  
  590.   sprintf(name,"%s%04d.pcx",base,num*3+2);
  591.   b=cash.reg("art/icons.spe",name,SPEC_IMAGE,1);
  592.  
  593.   sprintf(name,"%s%04d.pcx",base,num*3+3);
  594.   c=cash.reg("art/icons.spe",name,SPEC_IMAGE,1);
  595.  
  596.   h=cash.img(a)->height();
  597.  
  598.   return new ico_button(x,y,id,b,b,a,c,next,-1,key);
  599. }
  600.  
  601. ico_button *make_default_buttons(int x,int &y, ico_button *append_list)
  602. {
  603.   int h;
  604.   int diff_on;
  605.  
  606.   if (DEFINEDP(symbol_value(l_difficulty)))
  607.   {
  608.     if (symbol_value(l_difficulty)==l_extreme)
  609.       diff_on=3;
  610.     else if (symbol_value(l_difficulty)==l_hard)
  611.       diff_on=2;
  612.     else if (symbol_value(l_difficulty)==l_easy)
  613.       diff_on=0;
  614.     else 
  615.       diff_on=1;
  616.   } else  diff_on=3;
  617.  
  618.   
  619.   ico_button *start=load_icon(0,ID_START_GAME,x,y,h,NULL,"ic_start");                         y+=h;
  620.  
  621.   ico_switch_button *set=NULL;
  622.   if (!main_net_cfg || (main_net_cfg->state!=net_configuration::SERVER && main_net_cfg->state!=net_configuration::CLIENT))
  623.   {
  624.     set=new ico_switch_button(x,y,ID_NULL,diff_on,
  625.                          load_icon(3,ID_EASY,x,y,h,
  626.                          load_icon(8,ID_MEDIUM,x,y,h,
  627.                              load_icon(9,ID_HARD,x,y,h,
  628.                                      load_icon(10,ID_EXTREME,x,y,h,NULL,"ic_extreme"),
  629.                                   "ic_hard"),"ic_medium"),"ic_easy"),NULL);         y+=h;
  630.  
  631.   }
  632.  
  633.   ico_button *color=load_icon(4,ID_LIGHT_OFF,x,y,h,NULL,"ic_gamma");                          y+=h;  
  634.   ico_button *volume=load_icon(5,ID_VOLUME,x,y,h,NULL,"ic_volume");                            y+=h;
  635.   ico_button *sell=NULL;
  636.  
  637.   if (registered && prot)
  638.   {
  639.     sell=load_icon(11,ID_NETWORKING,x,y,h,NULL,"ic_networking");
  640.     y+=h;  
  641.   } else
  642.   {
  643.     sell=load_icon(2,ID_SHOW_SELL,x,y,h,NULL,"ic_sell");                           
  644.     y+=h;  
  645.   }
  646.   ico_button *quit=load_icon(6,ID_QUIT,x,y,h,NULL,"ic_quit");                                y+=h;
  647.  
  648.   if (set)
  649.   {
  650.     start->next=set;
  651.     set->next=color;
  652.   }
  653.   else start->next=color;
  654.  
  655.  
  656.   color->next=volume;  
  657.   if (sell)
  658.   {
  659.     volume->next=sell;  
  660.     sell->next=quit;
  661.   } else volume->next=quit;
  662.  
  663.   ico_button *list=append_list;
  664.  
  665.   if (append_list) 
  666.   { 
  667.     while (append_list->next) 
  668.       append_list=(ico_button *)append_list->next; 
  669.     append_list->next=start;
  670.   } else list=start;
  671.   
  672.   return list;  
  673. }
  674.  
  675.  
  676. ico_button *make_conditional_buttons(int x,int &y)
  677. {  
  678.   ico_button *start_list=NULL;
  679.   int h;
  680.   if (current_level)       // should we include a return icon?
  681.   {
  682.     start_list=load_icon(7,ID_RETURN,x,y,h,NULL,"ic_return");                       y+=h;
  683.   }
  684.     
  685.   
  686.   ico_button *load;
  687.   if (show_load_icon())
  688.   { load= load_icon(1,ID_LOAD_PLAYER_GAME,x,y,h,NULL,"ic_load");                     y+=h;}
  689.   else load=NULL;
  690.  
  691.   if (start_list) start_list->next=load;
  692.   else start_list=load;
  693.  
  694.   return start_list;   
  695. }
  696.  
  697. void main_menu()
  698. {
  699.   int y=yres/2-100;
  700.   ico_button *list=make_conditional_buttons(xres-33,y);
  701.   list=make_default_buttons(xres-33,y,list);
  702.  
  703.  
  704.   input_manager *inm=new input_manager(screen,eh,list);
  705.   inm->allow_no_selections();
  706.   inm->clear_current();
  707.  
  708.   time_marker old_time;
  709.  
  710.   screen->add_dirty(0,0,319,199);
  711.  
  712.   int eoff=0,coff=0;
  713.   event ev;
  714.  
  715.   int state=0,stop_menu=0;
  716.   time_marker start;
  717.   eh->flush_screen(); 
  718.   do
  719.   {
  720.     time_marker new_time;
  721.  
  722.     if (eh->event_waiting())
  723.     {
  724.       do { eh->get_event(ev); } while (ev.type==EV_MOUSE_MOVE && eh->event_waiting()); 
  725.       inm->handle_event(ev,NULL,eh);
  726.       if (ev.type==EV_KEY && ev.key==JK_ESC)
  727.         eh->push_event(new event(ID_QUIT,NULL));
  728.  
  729.       menu_handler(ev,inm);
  730.       start.get_time();
  731.       
  732.       eh->flush_screen();
  733.     }
  734.  
  735.     if (new_time.diff_time(&start)>10)
  736.     {
  737.       if (volume_window)
  738.         start.get_time();
  739.       else
  740.       {
  741.     if (!current_demo)
  742.     {
  743.       void *d=make_find_symbol("demos");
  744.       if (DEFINEDP(symbol_value(d)))
  745.       current_demo=symbol_value(d);
  746.     }
  747.     if (current_demo)
  748.     {
  749.       demo_man.set_state(demo_manager::PLAYING,lstring_value(CAR(current_demo)));
  750.       stop_menu=1;
  751.       current_demo=CDR(current_demo);
  752.     }
  753.       }
  754.     }
  755.  
  756.     if (volume_window) stop_menu=0;  // can't exit with colume window open
  757.     else if (main_net_cfg && main_net_cfg->restart_state()) stop_menu=1;
  758.     else if (the_game->state==RUN_STATE) stop_menu=1;
  759.     else if (ev.type==EV_MESSAGE)
  760.     {
  761.       if (ev.message.id==ID_START_GAME || ev.message.id==ID_RETURN) stop_menu=1;
  762.       else if (ev.message.id==ID_QUIT)
  763.       {
  764.     if (confirm_quit()) stop_menu=1;
  765.       else { ev.type=EV_SPURIOUS;       start.get_time(); }
  766.       }
  767.     }
  768.  
  769.   } while (!stop_menu);
  770.  
  771.   delete inm;
  772.  
  773.  
  774.   if (ev.type==EV_MESSAGE && ev.message.id==ID_QUIT)   // propogate the quit message
  775.     the_game->end_session();
  776.  
  777.  
  778. }
  779.  
  780.  
  781.